package com.xingchi.tornado.security.provider;

import com.xingchi.tornado.security.model.IUser;
import com.xingchi.tornado.security.model.LoginData;
import com.xingchi.tornado.security.model.MobileAuthenticationToken;
import com.xingchi.tornado.security.service.MobileCodeLoginRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.Assert;

/**
 * 手机号短信验证码认证
 *
 * @author xingchi
 * @date 2025/3/9 22:34
 */
@Slf4j
public class MobileAuthenticationProvider extends AbstractAuthenticationProvider {

    private final MobileCodeLoginRepository mobileCodeLoginRepository;

    public MobileAuthenticationProvider(MobileCodeLoginRepository mobileCodeLoginRepository) {
        this.mobileCodeLoginRepository = mobileCodeLoginRepository;
    }

    @Override
    public LoginData<? extends IUser> authenticateHandler(Authentication authentication) throws AuthenticationException {

        Assert.isInstanceOf(MobileAuthenticationToken.class, authentication, "MobileAuthenticationProvider only supports MobileAuthenticationToken");

        MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;

        // 参数校验
        paramsChecks(mobileAuthenticationToken);

        // 校验验证码是否正确
        String sendCode = mobileCodeLoginRepository.getCode(mobileAuthenticationToken.getMobile());
        if (StringUtils.isBlank(sendCode)) {
            throw new IllegalArgumentException("验证码已过期");
        }

        if (!sendCode.equals(mobileAuthenticationToken.getCode())) {
            throw new IllegalArgumentException("验证码错误");
        }

        // 查询用户信息
        IUser user = mobileCodeLoginRepository.loadUserByMobile(mobileAuthenticationToken.getMobile());
        if (user == null) {
            throw new IllegalArgumentException("用户不存在");
        }

        LoginData<IUser> loginData = LoginData.initLoginData();
        loginData.setUser(user);

        return loginData;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return MobileAuthenticationToken.class.isAssignableFrom(authentication);
    }

    protected void paramsChecks(MobileAuthenticationToken mobileAuthenticationToken) {

        // 判断手机号是否合法
        String mobile = mobileAuthenticationToken.getMobile();
        String code = mobileAuthenticationToken.getCode();

        if (mobile == null || code == null) {
            throw new IllegalArgumentException("手机号或验证码为空");
        }

        if (!mobile.matches("^1[3-9]\\d{9}$")) {
            throw new IllegalArgumentException("手机号不合法");
        }

        if (StringUtils.isBlank(code)) {
            throw new IllegalArgumentException("验证码不能为空");
        }
    }
}
